/**
 *
 */
package com.ybkj.daijia.server.service.impl;


import com.ybkj.daijia.serverUtils.HttpClientUtil;
import com.ybkj.daijia.Setting;
import com.ybkj.daijia.serverUtils.SettingUtils;
import com.ybkj.daijia.common.HtmlHelper;
import com.ybkj.daijia.common.Pager;
import com.ybkj.daijia.common.Principal;
import com.ybkj.daijia.config.SmsApi;
import com.ybkj.daijia.page.Page;
import com.ybkj.daijia.page.Pageable;
import com.ybkj.daijia.page.impl.PageImpl;
import com.ybkj.daijia.page.impl.PageRequest;
import com.ybkj.daijia.server.event.model.NoticeEvent;
import com.ybkj.daijia.server.mapper.CompanyMapper;
import com.ybkj.daijia.server.mapper.DriverMapper;
import com.ybkj.daijia.server.mapper.NoticeMapper;
import com.ybkj.daijia.server.mapper.NoticeXDriverMapper;
import com.ybkj.daijia.server.model.Company;
import com.ybkj.daijia.server.model.Driver;
import com.ybkj.daijia.server.model.Notice;
import com.ybkj.daijia.server.model.NoticeXDriver;
import com.ybkj.daijia.server.service.NoticeService;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.ApplicationEventMulticaster;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

/**
 * @author Shine
 */
@Service
public class DefaultNoticeService implements NoticeService {

    @Autowired
    private NoticeMapper noticeMapper;

    @Autowired
    private DriverMapper driverMapper;

    @Autowired
    private NoticeXDriverMapper noticeXDriverMapper;

    @Autowired
    private CompanyMapper companyMapper;

    @Autowired
    private ApplicationEventMulticaster applicationEventMulticaster;

    @Autowired
    private SettingUtils settingUtils;
    @Autowired
    private SmsApi smsApi;


    /* (non-Javadoc)
     * @see com.ybkj.shop.service.AdminService#queryAll()
     */
    public Page<Notice> queryAll() {

        Subject currentUser = SecurityUtils.getSubject();
        final Principal principal = (Principal) currentUser.getPrincipal();

        Pageable pageable = new PageRequest(Pager.getPage(), Pager.getLimit());

        List<Notice> content = new ArrayList<Notice>();
        int total = 0;

        if (!principal.isCompanyType()) {
            content = noticeMapper
                .selectByCompany(principal.getCompanyId(), Pager.getOffset(), Pager.getLimit());
            total = noticeMapper.countByCompany(principal.getCompanyId());
        } else {
            content = noticeMapper.selectByCompany(null, Pager.getOffset(), Pager.getLimit());
            total = noticeMapper.countByCompany(null);
        }

        if (total > 0) {
            for (Notice notice : content) {
                notice.setContent(HtmlHelper.html2Text(notice.getContent()));
            }
        }

        return new PageImpl<Notice>(content, pageable, total);

    }

    @Transactional(rollbackFor = Exception.class)
    public Notice save(Notice notice) {

        noticeMapper.insertRecord(notice);

        return notice;
    }


    @Transactional(rollbackFor = Exception.class)
    public void update(Notice notice) {

        noticeMapper.updateByPrimaryKey(notice);

    }

    @Override
    public Notice findOne(Long id) {

        return noticeMapper.selectByPrimaryKey(id);

    }

    @Override
    public NoticeXDriver findByDriverAndNotice(Long driverId, Long noticeId) {

        return noticeXDriverMapper.selectByDriverAndNotice(driverId, noticeId);

    }

    @Transactional(rollbackFor = Exception.class)
    public void delete(Notice notice) {

        noticeXDriverMapper.deleteByNotice(notice.getId());
        noticeMapper.deleteByPrimaryKey(notice.getId());

    }

    @Transactional(rollbackFor = Exception.class)
    public void create(String content, String contentMore, String name, String phone,
        String username,
        BigDecimal virtual, String startTime, String endTime,
        Long[] companyIds, Integer[] status, Boolean freeze, String[] type,
        String[] jobType, String sendTypes) {

        Subject subject = SecurityUtils.getSubject();
        Principal principal = (Principal) subject.getPrincipal();

        Setting setting = settingUtils.get();

        Date start = null;
        Date end = null;

        if (!StringUtils.isEmpty(startTime)) {
            try {
                start = DateUtils.parseDate(startTime, "yyyy-MM-dd");
                Calendar calendar = Calendar.getInstance();
                calendar.setTime(start);
                calendar.set(Calendar.HOUR_OF_DAY, 0);
                calendar.set(Calendar.MINUTE, 0);
                calendar.set(Calendar.SECOND, 0);

                start = calendar.getTime();
            } catch (ParseException e) {
                e.printStackTrace();
            }

        }

        if (!StringUtils.isBlank(endTime)) {
            try {
                end = DateUtils.parseDate(endTime, "yyyy-MM-dd");

                Calendar calendar = Calendar.getInstance();
                calendar.setTime(end);
                calendar.set(Calendar.HOUR_OF_DAY, 23);
                calendar.set(Calendar.MINUTE, 59);
                calendar.set(Calendar.SECOND, 59);

                end = calendar.getTime();
            } catch (ParseException e) {
                e.printStackTrace();
            }
        }

        String likeName = null;
        String likePhone = null;
        String likeUsername = null;

        if (StringUtils.isNotBlank(name)) {
            likeName = "%" + name + "%";
        }
        if (StringUtils.isNotBlank(phone)) {
            likePhone = "%" + phone + "%";
        }
        if (StringUtils.isNotBlank(username)) {
            likeUsername = "%" + username + "%";
        }

        if (principal.isCompanyType()) {
            if (null == companyIds) {
                List<Company> companylist = companyMapper.selectAll();
                companyIds = new Long[companylist.size()];
                for (int i = 0; i < companylist.size(); i++) {
                    companyIds[i] = companylist.get(i).getId();
                }
            }
        } else {
            companyIds = new Long[1];
            companyIds[0] = principal.getCompanyId();
        }

        if (null != jobType && jobType.length > 0) {
            for (int i = 0; i < jobType.length; i++) {
                jobType[i] = "%" + jobType[i] + "%";
            }
        }

        Notice notice = null;
        if (sendTypes.contains("message")) {
            notice = new Notice();
            notice.setCompanyId(principal.getCompanyId());
            notice.setContent(content);
            notice.setContentMore(contentMore);
            notice.setOperating(principal.getUsername());
            noticeMapper.insertRecord(notice);
        }

        Company mainCompany = companyMapper.selectMainCompany();

        for (int i = 0; i < companyIds.length; i++) {
            Long companyId = companyIds[i];
            Long[] realCompanyId = {companyId};

            Long count = driverMapper
                .countDriverList(realCompanyId, likeName, likePhone, likeUsername, start, end,
                    virtual, freeze, type, status, null, jobType, null);
            Integer rows = 1000;
            Integer totalPage = (int) (count / rows);
            if (count % rows != 0) {
                totalPage++;
            }
            Integer page = 0;
            if (totalPage > 0) {
                page = 1;
            }
            while (count > 0 && page <= totalPage) {
                List<Driver> newDriverList = driverMapper
                    .selectDriverList(realCompanyId, likeName, likePhone, likeUsername, start, end,
                        virtual, freeze, type, status, null, jobType, null, (page - 1) * rows, rows);

                if (sendTypes.contains("message")) {
                    if (!CollectionUtils.isEmpty(newDriverList)) {
                        for (Driver driver : newDriverList) {
                            NoticeXDriver noticeXDriver = new NoticeXDriver();
                            noticeXDriver.setDriverId(driver.getId());
                            noticeXDriver.setNoticeId(notice.getId());
                            noticeXDriver.setHasRead(false);
                            noticeXDriverMapper.insertRecord(noticeXDriver);
                        }
                        NoticeEvent noticeEvent = new NoticeEvent(notice, newDriverList);
                        applicationEventMulticaster.multicastEvent(noticeEvent);
                    }
                }

                if (sendTypes.contains("sms")) {
                    if (!CollectionUtils.isEmpty(newDriverList)) {
                        String url = "";
                        if (null != notice && StringUtils.isNotBlank(notice.getContentMore())) {
                            url = setting.getWebUrl() + "/driver/api/rest/v3/viewNotice/" + notice
                                .getId();
                            try {
                                url = HttpClientUtil.getShortUrl(url);
                            } catch (UnsupportedEncodingException e) {
                                e.printStackTrace();
                            }
                        }
                        StringBuilder phones = new StringBuilder();
                        for (int k = 0; k < newDriverList.size(); k++) {
                            Driver driver = newDriverList.get(k);
                            phones.append(driver.getPhone());
                            if (k != newDriverList.size() - 1) {
                                phones.append(",");
                            }
                        }

                        String signName = "";
                        if (setting.isSmsMainCompany()) {
                            signName = mainCompany.getSignName();
                        } else {
                            Company driverCompany = companyMapper
                                .selectByPrimaryKey(newDriverList.get(0).getCompanyId());
                            signName = driverCompany.getSignName();
                        }

                        smsApi.batchSendSms(phones.toString(),
                            content + url + "退订回复TD【" + signName + "】");
                    }
                }
                count = count - rows;
                page++;
            }
        }

    }

    @Override
    public Page<Map<String, Object>> queryNoticeV3(Long driverId, Integer page, Integer limit) {

        Setting setting = settingUtils.get();

        Pageable pageable = new PageRequest(page, limit);

        List<NoticeXDriver> content = noticeXDriverMapper
            .selectByDriver(driverId, page * limit, limit);
        long total = noticeXDriverMapper.countByDriver(driverId);

        List<Map<String, Object>> dataMapList = new ArrayList<Map<String, Object>>();
        if (total > 0) {
            for (NoticeXDriver noticeXDriver : content) {

                Notice notice = noticeMapper.selectByPrimaryKey(noticeXDriver.getNoticeId());
                Map<String, Object> dataMap = new HashMap<String, Object>();
                dataMap.put("id", notice.getId());
                if (StringUtils.isNotBlank(notice.getContent())) {
                    dataMap.put("content", notice.getContent());
                } else {
                    dataMap.put("content", "");
                }
                dataMap.put("hasRead", noticeXDriver.isHasRead());
                dataMap.put("created", noticeXDriver.getCreated().getTime());
                if (StringUtils.isNotBlank(notice.getContentMore())) {
                    String url =
                        setting.getWebUrl() + "/driver/api/rest/v4/viewNotice/" + notice.getId();
                    dataMap.put("url", url);
                } else {
                    dataMap.put("url", null);
                }
                dataMapList.add(dataMap);

            }
        }

        return new PageImpl<Map<String, Object>>(dataMapList, pageable, total);
    }

    @Transactional(rollbackFor = Exception.class)
    public void updateHasRead(Long id) {

        noticeXDriverMapper.updateHasRead(id);

    }

    @Override
    public Long countNotRead(Long driverId) {

        return noticeXDriverMapper.countNotRead(driverId);
    }

    @Transactional(rollbackFor = Exception.class)
    public void readAllNotice(Long driverId) {

        noticeXDriverMapper.readAllNotice(driverId);

    }


}
